package com.diy.sigmund.diycommon.util.encrypt;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.tomcat.util.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * DES加解密，弃用
 *
 * DES加密介绍
 *
 * DES 加密算法是一种 分组密码，以 64 位为 分组对数据 加密，它的 密钥长度 是 56 位，加密解密 用 同一算法。
 *
 * DES 加密算法是对 密钥 进行保密，而 公开算法，包括加密和解密算法。这样，只有掌握了和发送方 相同密钥 的人才能解读由 DES加密算法加密的密文数据。因此，破译 DES 加密算法实际上就是 搜索密钥的编码。对于 56 位长度的 密钥 来说，如果用 穷举法 来进行搜索的话，其运算次数为 2 ^ 56 次。
 * ————————————————
 * 版权声明：本文为CSDN博主「零壹技术栈」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
 * 原文链接：https://blog.csdn.net/baidu_22254181/article/details/82594072
 *
 * DES是一种对称加密算法，所谓对称加密算法即：加密和解密使用相同密钥的算法。DES加密算法出自IBM的研究，
 * 后来被美国政府正式采用，之后开始广泛流传，但是近些年使用越来越少，因为DES使用56位密钥，以现代计算能力，
 * 24小时内即可被破解。虽然如此，在某些简单应用中，我们还是可以使用DES加密算法，本文简单讲解DES的JAVA实现。
 * 注意：DES加密和解密过程中，密钥长度都必须是8的倍数
 *
 * @author ylm-sigmund
 * @since 2021/8/17 15:33
 */
@Deprecated
public class DESHelper {

    private final static String DES = "DES";
    private final static String KEY = "abcdef0123456789";

    private static final Logger log = LoggerFactory.getLogger(DESHelper.class);

    public DESHelper() {
    }

    public static String encrypt(String plaintext) throws Exception {

        return encodeBase64(encryptDES(plaintext, KEY));
    }

    public static String encrypt(String plaintext, String key) throws Exception {
        return encodeBase64(encryptDES(plaintext, key));
    }

    public static String decrypt(String cipherText) {
        return decryptDES(decodeBase64(cipherText.getBytes()), KEY);
    }

    public static String decrypt(String cipherText, String key) throws Exception {
        return decryptDES(decodeBase64(cipherText.getBytes()), key);
    }

    /**
     * base64编码
     *
     * @param binaryData 字节数组
     * @return String
     * @throws Exception Exception
     */
    private static String encodeBase64(byte[] binaryData) throws Exception {
        try {
            return Base64.encodeBase64String(binaryData);
        } catch (Exception e) {
            log.error("error", e);
            throw new Exception("BASE64编码失败!");
        }
    }

    /**
     * Base64解码
     *
     * @param binaryData 字节数组
     * @return byte[]
     */
    private static byte[] decodeBase64(byte[] binaryData) {
        try {
            return Base64.decodeBase64(binaryData);
        } catch (Exception e) {
            log.error("error", e);
            throw new RuntimeException("BASE64解码失败！");
        }
    }

    private static byte[] encryptDES(String data, String key) {

        try {
            // 生成一个可信任的随机数源 ,  SHA1PRNG: 仅指定算法名称
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            // 从原始密钥数据创建DESKeySpec对象
            DESKeySpec deskey = new DESKeySpec(key.getBytes(StandardCharsets.UTF_8));

            //创建一个密匙工厂，然后用它把DESKeySpec转换成
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
            SecretKey secretKey = keyFactory.generateSecret(deskey);
            //Cipher对象实际完成加密操作
            Cipher cipher = Cipher.getInstance(DES);
            //用密匙初始化Cipher对象,
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, random);
            //现在，获取数据并加密
            //正式执行加密操作
            return cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));

        } catch (Exception e) {
            log.error("error", e);
        }
        return null;
    }

    private static String decryptDES(byte[] data, String key) {

        try {
            // 算法要求有一个可信任的随机数源,  SHA1PRNG: 仅指定算法名称
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            // 创建一个DESKeySpec对象
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes(StandardCharsets.UTF_8));
            // 创建一个密匙工厂
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
            // 将DESKeySpec对象转换成SecretKey对象
            SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
            // Cipher对象实际完成解密操作
            Cipher cipher = Cipher.getInstance(DES);
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, secretKey, random);
            // 真正开始解密操作
            return new String(cipher.doFinal(data), StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("error", e);
        }
        return null;
    }

    public static void main(String[] args) throws Exception {
        final String decrypt = DESHelper.decrypt(
                "tyQEctOtnGIGQT6z5ssarOnId6YA+8/m2XnVhhjRGZWr3/X1PjIc1jXq758/H2+e3BJDYqMWSMoJppjl4z1Jy/9x6Gp4w2cXPKoeU0FAYgf0ICNTnuDTJDxBl4qfrzRXiUO4ChPX4Zt4TnFhvwZEPnoO3aRLYskiXRU5c1oT2t0VnYdDK/4I0HoO3aRLYskiXRU5c1oT2t2d6+99+EwWexewdcxulvBL+ihRs4eNdiMtJBmzafPCynoO3aRLYskiBZ6EptomcZqU0s50jueb2A==");
        System.out.println(decrypt);
    }
}
